from PyQt4.QtGui import QPushButton
from phonik.plugin import UIPlugin
from phonik.plugin import Plugin, UIPlugin
from PyQt4.QtCore import SIGNAL
from PyQt4.QtGui import QFont
from PyQt4.QtGui import QListView
from PyQt4.QtCore import SLOT
from PyQt4.QtCore import QObject
from PyQt4.QtGui import QSplitter
from PyQt4.QtGui import QWidget
from PyQt4.QtGui import QHBoxLayout
from PyQt4.QtGui import QAbstractItemView
from PyQt4 import QtGui
from PyQt4.QtGui import QColumnView
from PyQt4.QtGui import QTableView
from PyQt4.QtGui import QVBoxLayout
from PyQt4.QtCore import QSize
from PyQt4.QtGui import QDirModel, QCursor
from PyQt4.QtCore import QDir, QStringList
from PyQt4.QtCore import Qt, QString, QMimeData, QVariant, QFileSystemWatcher
from PyQt4.QtGui import qApp, QMenu, QAction, QFileDialog, QDesktopServices, QApplication
from PyQt4 import QtCore

import os, sys
import shutil
import time
import thread

class FileBrowser(UIPlugin):
    def load(self):

    # last visited path - used for file monitoring
        self.lastPath = ''

        # set plugin name
        self.setName('Files')

        # create widgets
        mainWidget = QWidget(self.mw)
        self.verticalLayout = QVBoxLayout(mainWidget)
        self.verticalLayout.setMargin(0)
        self.verticalLayout.setSpacing(0)

        self.splitter = QSplitter(mainWidget)
        self.splitter.setOrientation(Qt.Vertical)

        # create files view and model
        self.view = ColumnView(mainWidget)
        self.view.setFocusPolicy(Qt.NoFocus)
        self.view.setIconSize(QSize(16, 16))
        self.view.setFont(QFont("Sans", 9))
        self.view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.view.customContextMenuRequested.connect(self.showContextMenu)
        self.view.setResizeGripsVisible(False)


        # set model
        self.model = DirModel()
        self.view.setModel(self.model)

        # drag and drop
        self.view.setDragDropMode(QAbstractItemView.DragDrop)
        self.view.setDragEnabled(True)
        self.view.setAcceptDrops(True)

        # set root dir
        if self.hasOption('musicdir'):
            self.view.setRootIndex(self.model.index(QString.fromUtf8(self.get('musicdir'))))
        else:
            self.view.setRootIndex(self.model.index(QDesktopServices.storageLocation(QDesktopServices.MusicLocation)))

        self.splitter.addWidget(self.view)
        self.splitter.addWidget(self.playlist)
        self.splitter.setHandleWidth(2)

        # store splitter handle position
        if self.hasOption('splitter.handle.pos'):
            self.splitter.restoreState(self.get('splitter.handle.pos'))

        self.verticalLayout.addWidget(self.splitter)

        # crate menu
        self.createMenu()

        # add page to the main window
        self.addPage(mainWidget)

        # signals
        self.view.clicked.connect(self.clicked)
        self.view.doubleClicked.connect(self.doubleClicked)
        self.playlist.clicked.connect(self.playlistClicked)

        # start file system watcher
        self.watcher = QFileSystemWatcher()
        self.watcher.addPath(self.model.filePath(self.view.rootIndex()))
        self.watcher.directoryChanged.connect(self.directoryChanged)


    def directoryChanged(self):
        self.model.refresh(self.view.rootIndex())


    def unload(self):
        self.set('splitter.handle.pos', self.splitter.saveState())
        self.set('musicdir', str(self.model.filePath(self.view.rootIndex()).toUtf8()))


    def showContextMenu(self, pos):
        actionList = [QAction(self.tr('Remove'), self.view)]
        result = QMenu().exec_(actionList, QCursor.pos())
        if result:
            if result.text() == self.tr('Remove'):
                index = self.view.indexAt(pos)
                path = str(self.model.filePath(index).toUtf8())
                if os.path.isdir(path):
                    shutil.rmtree(path)
                else:
                    os.remove(path)
                self.model.refresh(self.model.index(QString.fromUtf8(os.path.dirname(path))))

    def createMenu(self):
        self.menuFiles = QMenu(self.getMenuBar())
        self.menuFiles.setTitle(self.tr('Files'))

        self.actionSelectMusicDir = QAction(self.tr('Select the music folder'), self.mw)
        self.actionSelectMusicDir.triggered.connect(self.selectMusicDir)
        self.menuFiles.addAction(self.actionSelectMusicDir)

        self.getMenuBar().addAction(self.menuFiles.menuAction())


    def selectMusicDir(self):
        dir = QFileDialog.getExistingDirectory(self.mw, self.tr('Select the music folder'),
                                               QDesktopServices.storageLocation(QDesktopServices.MusicLocation),
                                               QFileDialog.ShowDirsOnly)
        if dir:
            self.view.setRootIndex(self.model.index(dir))


    def clicked(self, index):
        self.model.refresh(self.view.rootIndex())
        if self.lastPath:
            self.watcher.removePath(self.lastPath)
        self.lastPath = self.model.filePath(index)
        self.watcher.addPath(self.lastPath)


    def doubleClicked(self, index):
        path = str(self.model.filePath(index).toUtf8())

        self.playlist.clear()

        if os.path.isdir(path):
            autosort = False

            for root, dirs, files in os.walk(path):
                if dirs:
                    autosort = True
                for name in files:
                    filePath = os.path.join(root, name)

                    if self.informer.hasAudio(filePath):
                        self.addToPlaylist(filePath)

                    # sort playlist
            if autosort:
                self.playlist.autosort()
            else:
                self.playlist.sort()

        else:
            if self.informer.hasAudio(path):
                self.addToPlaylist(path)

        self.playlist.selectFirst()
        self.player.play(self.playlist.getSongURI(0))



    def addToPlaylist(self, path, autosort=False):
        url, info, tags = self.informer.getInfo(path)
        if info:
            self.playlist.addSong(url, info, tags, autosort)


    def playlistClicked(self, index):
        path = self.playlist.getSongURI(index.row())
        self.player.play(path)


class ColumnView(QColumnView):
    def __init__(self, parent):
        QColumnView.__init__(self, parent)
        self.__parent = parent


    def createColumn(self, index):
        view = QListView(self.viewport())

        self.initializeColumn(view)

        view.setRootIndex(index)
        if (self.model().canFetchMore(index)):
            self.model().fetchMore(index)

        # fit width
        tmpSize = 0
        biggestString = None
        for i in range(view.model().rowCount(index)):
            lineString = view.model().index(i, 0, index).data(Qt.DisplayRole ).toString()
            lineSize = lineString.size()
            if lineSize > tmpSize:
                tmpSize = lineSize
                biggestString = lineString


        if biggestString:
            fontMetrics = view.fontMetrics()
            width = fontMetrics.boundingRect(biggestString).width()
            view.setFixedWidth(width+70)

        return view
    
    


class DirModel(QDirModel):
    def __init__(self):
        QDirModel.__init__(self)


    def dropMimeData(self, data, action, row, column, parent):
        if action == Qt.IgnoreAction:
            return True

        elif 'text/uri-list' in data.formats():
            dest = self.filePath(parent)

            files = []
            for url in data.urls():
                files.append(str(url.path().toUtf8()))

            filesStr = '//\\\\'.join(files)

            menu = QMenu()

            copyAction = menu.addAction(self.tr('Copy'))
            copyAction.setProperty('action', 'copy')
            copyAction.setProperty('files', filesStr)
            copyAction.setProperty('dest', dest)

            moveAction = menu.addAction(self.tr('Move'))
            moveAction.setProperty('action', 'move')
            moveAction.setProperty('files', filesStr)
            moveAction.setProperty('dest', dest)

            menu.triggered.connect(self.showMenu)
            menu.exec_(QCursor.pos())

        return False


    def showMenu(self, action):
        dest = unicode(action.property('dest').toString().toUtf8(), 'utf-8')

        files = unicode(action.property('files').toString(), 'utf-8').split('//\\\\')

        try:
            if action.property('action').toString() == 'copy':
                for file in files:
                    if os.path.isdir(file):
                        shutil.copytree(file, dest + os.sep + os.path.basename(file))
                    else:
                        shutil.copy(file, dest)

                    self.refresh(self.index(file))

            if action.property('action').toString() == 'move':
                for file in files:
                    shutil.move(file, dest + os.sep + os.path.basename(file))

                    self.refresh(self.index(file))

            self.refresh(self.index(dest))
        except OSError, ose:
            print ose


    def flags(self, index):
        return Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled | Qt.ItemIsEnabled | Qt.ItemIsSelectable
